#ifndef _DERIVED_H_
#define _DERIVED_H_

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <MyPointers.h>

class Base
{
public:
   virtual ~Base(){;}
   virtual void printName()
   { std::cout << "Base" << std::flush; }

   void printLocal()
   { std::cout << "Local: Base" << std::flush; }
};

class Child1 : public Base
{
public:
   virtual ~Child1(){;}
   virtual void printName()
   { std::cout << "Child1" << std::flush; }

   void printLocal()
   { std::cout << "Local: Child1" << std::flush; }
};

class Child2 : public Base
{
public:
   virtual ~Child2(){;}
   virtual void printName()
   { std::cout << "Child2" << std::flush; }

   void printLocal()
   { std::cout << "Local: Child2" << std::flush; }
};

class GrandChild1 : public Child1
{
public:
   virtual ~GrandChild1(){;}
   virtual void printName()
   { std::cout << "GrandChild1" << std::flush; }

   void printLocal()
   { std::cout << "Local: GrandChild1" << std::flush; }
};

my_ptr<Base> createRandomPtr()
{
   const int num_classes(4);
   const int rnd_class(random()%num_classes);

   my_ptr<Base> ret_obj;
   switch(rnd_class)
   {
   case 0: ret_obj = my_ptr<Base>(new Base); break;
   case 1: ret_obj = my_ptr<Base>(new Child1); break;
   case 2: ret_obj = my_ptr<Base>(new Child2); break;
   case 3: ret_obj = my_ptr<Base>(new GrandChild1); break;
   }

   return ret_obj;
}

void examineDerived(my_ptr<Base> base)
{
   std::cout << "Examining...\n";
   base->printName();
   base->printLocal();
}


std::vector<my_ptr<Base> > createRandomList()
{
   const unsigned num(10);
   std::vector<my_ptr<Base> > ret_vec;
   for(unsigned i=0;i<num;++i)
   {
      ret_vec.push_back(createRandomPtr());
   }
   return ret_vec;
}


#endif
